package org.jeecg.modules.mr.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysVarModel;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.dynamic.db.DynamicDBUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.arc.entity.ArcCustomers;
import org.jeecg.modules.arc.entity.ArcMeterReplaces;
import org.jeecg.modules.arc.entity.BasePeriod;
import org.jeecg.modules.arc.service.*;
import org.jeecg.modules.arc.vo.BaseWaterPricesVo;
import org.jeecg.modules.bl.entity.BlDiscountFees;
import org.jeecg.modules.bl.entity.BlExpenses;
import org.jeecg.modules.bl.entity.BlSubDiscounts;
import org.jeecg.modules.bl.entity.BlSubExpenses;
import org.jeecg.modules.bl.service.IBlDiscountFeesService;
import org.jeecg.modules.bl.service.IBlDiscountsService;
import org.jeecg.modules.bl.service.IBlExpensesService;
import org.jeecg.modules.bl.vo.BlExpensesPage;
import org.jeecg.modules.bl.vo.RecordMEArrearVo;
import org.jeecg.modules.chg.entity.ChgArrearExpenses;
import org.jeecg.modules.chg.entity.ChgArrears;
import org.jeecg.modules.chg.entity.ChgSubArrear;
import org.jeecg.modules.chg.service.IChgArrearExpensesService;
import org.jeecg.modules.chg.service.IChgArrearsService;
import org.jeecg.modules.chg.service.IChgFeesService;
import org.jeecg.modules.chg.vo.ChgArrearsPage;
import org.jeecg.modules.mr.entity.*;
import org.jeecg.modules.mr.mapper.MrRecordsMapper;
import org.jeecg.modules.mr.service.IMrAuditsService;
import org.jeecg.modules.mr.service.IMrChangesService;
import org.jeecg.modules.mr.service.IMrRecordsService;
import org.jeecg.modules.mr.service.IMsMeasuresService;
import org.jeecg.modules.mr.vo.*;
import org.jeecg.modules.online.cgform.entity.OnlCgformField;
import org.jeecg.modules.online.cgform.entity.OnlCgformHead;
import org.jeecg.modules.online.cgform.service.IOnlCgformFieldService;
import org.jeecg.modules.online.cgform.service.IOnlCgformHeadService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * @Description: 抄表记录
 * @Author: jeecg-boot
 * @Date:   2022-02-03
 * @Version: V1.0
 */
@Service
public class MrRecordsServiceImpl extends ServiceImpl<MrRecordsMapper, MrRecords> implements IMrRecordsService {

    @Resource
    private MrRecordsMapper recordsMapper;
    @Autowired
    private IArcCustomersService customersService;
    @Autowired
    private IMrRecordsService recordsService;
    @Autowired
    private IBasePeriodService basePeriodService;
    @Autowired
    private IArcMeterReplacesService replacesService;
    @Autowired
    private IArcAdjustedConfigsService adjustedConfigsService;
    @Autowired
    private IMsMeasuresService measuresService;
    @Autowired
    private IMrAuditsService auditsService;
    @Autowired
    private IOnlCgformFieldService cgformFieldService;
    @Autowired
    private IOnlCgformHeadService cgformHeadService;
    @Autowired
    private IMrChangesService changesService;
    @Autowired
    private IBaseWaterPricesService waterPricesService;
    @Autowired
    private IBlDiscountsService discountsService;
    @Autowired
    private IBlDiscountFeesService discountFeesService;
    @Autowired
    private IBlExpensesService expensesService;
    @Autowired
    private IChgArrearsService arrearsService;
    @Autowired
    private IChgArrearExpensesService arrearExpensesService;
    @Autowired
    private IChgFeesService chgFeesService;
    @Autowired
    private ISysBaseAPI baseAPI;

    //手工抄表录入
    @Override
    @Transactional
    public Result<?> readManual(ReadRecordVo recordVo){
        /***
         * 1.验证是否需要抄表
         * 2.验证是否已审核
         * 3.
         */
        try {
            ArcCustomers customers = customersService.getById(recordVo.getCustomerId());
            if(null == customers ){
                //水表户不存在
                return Result.error("水表户不存在");
            }
            if( customers.getIsRead() != 1){
                //本月不需要抄表
                return Result.error("本月不需要抄表");
            }
            if( "8".equals(customers.getWaterReadCycle())){
                //一月多抄

            }

            if(queryCusIsReaded(recordVo.getCustomerId(),recordVo.getId())){
               //已抄表审核  抄表没审核可以继续修改抄表
                return Result.error("抄表已审核");
            };

            //继续- 未抄、已抄表未审核
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

            //if(oConvertUtils.istEmpty(recordVo.getre))

            String month = DateUtils.getDate("yyyyMM");
            String upMonth = DateUtils.diffMonth(month, 3);


            //是否存在 与往月存在用水量（0度不算）大于0的起度相同
            int count = recordsService.count(new LambdaQueryWrapper<MrRecords>()
                    .eq(MrRecords::getCustomerId, recordVo.getCusCode())//换成code
                    .eq(MrRecords::getBeginScale, recordVo.getBeginScale())
                    .eq(MrRecords::getIsVaild, 1)
                    .gt(MrRecords::getReadMonth,upMonth) //大于近三个月的
                    .gt(MrRecords::getAmount, 0)//用水量大于0
                    .eq(MrRecords::getDelFlag, 0));
            if(count>0){
                return Result.error( "本月的开始起度与往月存在用水量的起度相同，请到【基础数据】-【水表用户】-【批量修改】-【是否修改水表止度】修改最新水表止度");
            }

            List<MrRecords> recordsList = recordsService.list(new LambdaQueryWrapper<MrRecords>()
                    .eq(MrRecords::getCustomerId, recordVo.getCusCode())//换成code
                    .eq(MrRecords::getReadMonth, month)
                    .eq(MrRecords::getIsVaild, 1)
                    .eq(MrRecords::getAuditStatus, 0)//未审核
                    .eq(MrRecords::getDelFlag, 0));
            if(null != recordsList && recordsList.size()>0){
                //当月已存在抄表的记录，这里可以直接修改 为无效，再新增一条

                // 20240522 当月已抄未审核的记录，重新提交，起度是记录起度，不用前端传递过来的

                MrRecords mrRecords = recordsList.get(0);

                MrRecords records = new MrRecords();
                BeanUtils.copyProperties(mrRecords,records);

                if(null != recordVo.getEndScale() && recordVo.getEndScale().intValue()>0){

                    //先刪除原記錄
                    mrRecords.setDelFlag(1);
                    recordsMapper.updateById(mrRecords);

                    records.setId(null);
                    records.setEndScale(recordVo.getEndScale());
                    //止度-起度，重新计算水量，不用前端传递过来的
                    records.setEndScale(recordVo.getEndScale());
                    BigDecimal scale = records.getEndScale().subtract(records.getBeginScale()).setScale(0, BigDecimal.ROUND_HALF_DOWN);
                    recordVo.setAmount(scale);

                    records.setWaterUsedType(recordVo.getWaterUsedType());
                    if(oConvertUtils.isEmpty(recordVo.getWaterReadInput())){
                        records.setWaterReadInput("1");//录入方式-1手动2移动端
                    }else{
                        records.setWaterReadInput(recordVo.getWaterReadInput());//录入方式-移动端
                    }
                    records.setReadTime(DateUtils.parseDate(recordVo.getReadTime(),"yyyy-MM-dd"));
                    records.setRemark(recordVo.getRemark());
                    records.setReaderId(sysUser.getUsername());
                    recordsMapper.insert(records);
                }

                //更新最后抄表止度
                if(null != recordVo.getEndScale() && recordVo.getEndScale().intValue()>0){
                    customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                            .set(ArcCustomers::getLastReadScale,records.getEndScale())
                            .eq(ArcCustomers::getId, recordVo.getCustomerId()));
                }
            }else {
                MrRecords records = new MrRecords();
                records.setWaterReadType(customers.getWaterUseType());
                records.setBeginScale(recordVo.getBeginScale());
                records.setCustomerId(recordVo.getCusCode());
                records.setCusName(recordVo.getCusName());
                records.setReadMonth(month);
                records.setBookId(recordVo.getBookId());
                records.setEndScale(recordVo.getEndScale());
                records.setAmount(recordVo.getAmount());
                records.setWaterUsedType(recordVo.getWaterUsedType());
                if(oConvertUtils.isEmpty(recordVo.getWaterReadInput())){
                    records.setWaterReadInput("1");//录入方式-1手动2移动端
                }else{
                    records.setWaterReadInput(recordVo.getWaterReadInput());//录入方式-移动端
                }
                records.setReadTime(DateUtils.parseDate(recordVo.getReadTime(),"yyyy-MM-dd"));
                records.setRemark(recordVo.getRemark());
                records.setReaderId(sysUser.getUsername());
                records.setIsNeedAudit(1);
                recordsMapper.insert(records);

                String format = String.format("%s =  %s - %s", "unread_times", "unread_times", 1);
                customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                        .setSql(format)
                        .set(ArcCustomers::getLastReadScale,records.getEndScale())//最后抄表止度
                        .eq(ArcCustomers::getId, recordVo.getCustomerId())
                        .gt(ArcCustomers::getUnreadTimes,-1));
            }
        }catch (Exception e){
           log.error(e.getMessage());
           return Result.error( e.getMessage());
        }
        return Result.OK("OK");
    }
    //手工抄表录入-删除
    @Override
    @Transactional
    public Result<?> readDelManual(ReadRecordVo recordVo){
        /***
         * 1.验证是否需要抄表
         * 2.验证是否已审核
         * 3.是否存在
         */

        try {
            ArcCustomers customers = customersService.getById(recordVo.getCustomerId());
            if(null == customers ){
                //水表户不存在
                return Result.error("水表户不存在");
            }
            if( customers.getIsRead() != 1){
                //本月不需要抄表
                return Result.error("本月不需要抄表");
            }

            if(queryCusIsReaded(recordVo.getCustomerId(),recordVo.getId())){
               //已抄表审核  抄表没审核可以继续修改抄表
                return Result.error("本次抄表已审核");
            };

            //继续- 未抄、已抄表未审核
            String month = DateUtils.getDate("yyyyMM");

            List<MrRecords> recordsList = recordsService.list(new LambdaQueryWrapper<MrRecords>()
                    .eq(MrRecords::getCustomerId, recordVo.getCusCode())
                    .eq(MrRecords::getReadMonth, month)
                    .eq(MrRecords::getIsVaild, 1)
                    .eq(MrRecords::getAuditStatus, 0)//未审核
                    .eq(MrRecords::getDelFlag, 0));
            if(null != recordsList && recordsList.size()>0){
                //当月已存在抄表的记录，这里可以直接修改 为无效，
                MrRecords mrRecords = recordsList.get(0);
                mrRecords.setDelFlag(1);
                mrRecords.setIsVaild(0);
                recordsMapper.updateById(mrRecords);

                String format = String.format("%s =  %s + %s", "unread_times", "unread_times", 1);
                String format2 = String.format("%s <=  %s", "unread_times", "readTimes");
                customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                        .setSql(format)
                        .set(ArcCustomers::getLastReadScale,mrRecords.getBeginScale())//最后抄表止度
                        .eq(ArcCustomers::getId, recordVo.getCustomerId())
                );
            }
        }catch (Exception e){
           log.error(e.getMessage());
           return Result.error( e.getMessage());
        }
        return Result.OK("OK");
    }

    /**
     * 远程抄表
     * @param manholeVal 远程表序列号-字段值
     * @return
     */
    @Override
    public List<Map<String, Object>> readRemote(String manholeVal){
        SysVarModel remoteModel = baseAPI.querySysVar("remote_meter_dbkey");//远程水表动态数据源Key
        if(null != remoteModel){
            // remote_213,jeecg-boot,yccb_sbcb,sbnm,sjyl,addtime
            String[] values = remoteModel.getValue().split(",");
            String sql="select "+ values[4]  +" as 'driveReadData',"
                    + values[3]+" as 'uniqueId'"
                    +" from "+values[2]
                    +" where "+values[3]+"='"+manholeVal+"' order by "+values[5]+ " desc limit 1";
            return DynamicDBUtil.findList(values[0], sql, null);
        }else{
            return null;
        }
    }

    //当前月份是否存在已审的抄表记录
    @Override
    public Boolean queryCusIsReaded(String cusId,String id) {
        Integer index = recordsMapper.queryCusIsReaded(cusId,id);
        if(null != index && index>0){
            return true;
        }
        return false;
    }

    //批量审核
    @Override
    @Transactional
    public Result<Object> auditsBatch(List<String> rdList, Integer isPass, String note) throws JeecgBootException, ParseException {
        /***
         * 1.生成计量清单(有财务月份)、计量清单明细
         *     是否阶段计费
         *     是否有换表记录
         *     是否有总分表
         *     是否有考核表
         *     是否有减免水量记录
         * 2. 生成水量审核记录
         * 3. 生成计费清单
         *      是否是优惠用户
         * 4. 生成欠费记录
         * 5. 减少用户水表的待抄次数
         *
         *
         * 修改水量保存时会校验 三种情况（已抄未审，本月已审，往月水量）这里不考虑
         */

        BasePeriod basePeriod = basePeriodService.getOne(
                new LambdaQueryWrapper<BasePeriod>()
                        .eq(BasePeriod::getIsUsed,1));
        //当前财务会计期间月份
        String finMonth = basePeriod.getMonth();
        //当前抄表月份
        String readMonth = DateUtils.getDate("yyyyMM");

        Integer lastAmount=0;
        try {
            SysVarModel lastAmountModel = baseAPI.querySysVar("last_amount");//保底最低用量
            if(null == lastAmountModel){
                lastAmountModel=new SysVarModel();
                lastAmountModel.setValue("0");
            }
            if(oConvertUtils.isNotEmpty(lastAmountModel.getValue())){
                lastAmount=Integer.parseInt(lastAmountModel.getValue());
            }
        }catch (Exception e){
            lastAmount=0;
        }

        //已抄过的水表用户ID集
        List<String> cusIds=new ArrayList<>();
        //查询抄表记录计量信息-抄表数据、用水性质数据、阶段用量数据
        List<ReadRecordVo> readRecordVos = queryReadMeasureRecord(rdList);// recordVo.getCustomerId() 就是cusCode

        for (ReadRecordVo recordVo : readRecordVos) {
            if(null != recordVo.getAuditStatus() && recordVo.getAuditStatus() == 1){
                continue;
            }
            if (isPass == 1) {

                //是否有换表水量
                BigDecimal replaceAmount = new BigDecimal(0.0);
                BigDecimal replaceScale = new BigDecimal(0.0);
                JSONObject replaceObj = queryReplace(isPass, readMonth, recordVo.getCustomerId());
                replaceAmount = replaceObj.getBigDecimal("replaceAmount");
                replaceScale = replaceObj.getBigDecimal("replaceScale");
                //是否预开票户
                Integer isPreinvoiced = recordVo.getIsPreinvoiced();

                /**修改此条抄表记录已存在审核记录，但没通过，是允许再审，但之前的作废，重新*/
                auditsService.update(new LambdaUpdateWrapper<MrAudits>()
                        .set(MrAudits::getIsVaild, 0)
                        .eq(MrAudits::getRecordId, recordVo.getId())
                        .eq(MrAudits::getIsVaild, 1)
                        .eq(MrAudits::getDelFlag, 0)
                        .eq(MrAudits::getIsPassed, 0));
                /**修改此条抄表记录已存在计量记录 作为无效 **/
                measuresService.update(new LambdaUpdateWrapper<MsMeasures>()
                        .set(MsMeasures::getIsVaild, 0)
                        .eq(MsMeasures::getRecordId, recordVo.getId())
                        .eq(MsMeasures::getIsVaild, 1)
                        .eq(MsMeasures::getDelFlag, 0));

                //是否保底量,仅抄见水量，保底，
                if (lastAmount > 0) {
                    if (recordVo.getAmount().doubleValue() < lastAmount) {
                        recordVo.setAmount(new BigDecimal(lastAmount));
                    }
                }

                //计量
                if(1 == recordVo.getIsCalculated()){
                    if(null == recordVo.getTier0()){
                        throw new JeecgBootException(recordVo.getCustomerId()+"用水性质没有对应的用水价格");
                    }

                    MsMeasuresPage measurePage = createMeasurePage(recordVo, readMonth, finMonth, replaceScale, replaceAmount);
                    MsMeasures msMeasures = new MsMeasures();
                    BeanUtils.copyProperties(measurePage, msMeasures);
                    int count=measuresService.saveMain(msMeasures, measurePage.getMsSubMeasuresList());
                    if(count == -1){
                       throw new JeecgBootException("该抄表记录已审核");
                    }

                    /**存在增减水量策略优惠的，记录下来*/
                    if (msMeasures.getAjustedAmount().doubleValue() > 0) {
                        //水量优惠记录 mws_t_mr_ajusted
                        String code = "402881a57ee161d4017ee1621ee70001";
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("customer_id", recordVo.getCustomerId());
                        jsonObject.put("cus_name", recordVo.getCusName());
                        jsonObject.put("record_id", msMeasures.getRecordId());
                        jsonObject.put("read_month", msMeasures.getReadMonth());
                        jsonObject.put("amount", msMeasures.getAjustedAmount());
                        jsonObject.put("is_passed", 1);
                        createOnlineData(code, jsonObject);
                    }

                    //计费
                    if(1 == recordVo.getIsCalculated()){
                        BlExpensesPage expensesPage = createExpense(recordVo, measurePage);
                        BlExpenses expenses = new BlExpenses();
                        BeanUtils.copyProperties(expensesPage, expenses);
                        expenses.setMeasureId(msMeasures.getId());
                        //保存 存在杂项则合并计费 --存在一月多抄的，
                        expensesService.saveMain(expenses, expensesPage.getBlSubExpensesList(),recordVo.getWaterReadCycle());
                        /***存在计费优惠的 记录下来*/
                        if (expensesPage.getDiscountMoney().doubleValue() > 0) {
                            for (BlSubExpenses blSubExpenses : expensesPage.getBlSubExpensesList()) {
                                //记录优惠费用记录
                                if (blSubExpenses.getDiscountMoney().doubleValue() > 0) {
                                    BlDiscountFees discountFees = new BlDiscountFees();
                                    discountFees.setCusName(measurePage.getCusName());
                                    discountFees.setCustomerId(measurePage.getCustomerId());
                                    discountFees.setDiscountId(blSubExpenses.getDiscountId());
                                    discountFees.setItemCode(blSubExpenses.getItemCode());
                                    discountFees.setNatureId(recordVo.getNatureId());
                                    discountFees.setExpenseId(expenses.getId());
                                    discountFees.setSubExpenseId(blSubExpenses.getId());
                                    discountFees.setTierNo(blSubExpenses.getTierNo());
                                    discountFees.setMoney(blSubExpenses.getDiscountMoney());
                                    discountFeesService.save(discountFees);
                                }
                            }
                        }

                        //欠费记录
                        ChgArrearsPage arrearsPage = arrearsService.createArrears(isPreinvoiced
                                , JSONObject.parseObject(JSON.toJSONString(msMeasures))
                                , expenses, expensesPage.getBlSubExpensesList());
                        ChgArrears arrears = new ChgArrears();
                        BeanUtils.copyProperties(arrearsPage, arrears);
                        //保存 存在杂项则合并欠费
                        arrearsService.saveMain(arrears, arrearsPage.getChgSubArrearList(),recordVo.getWaterReadCycle());

                        //欠费与计费关联
                        ChgArrearExpenses arrearExpenses = new ChgArrearExpenses();
                        arrearExpenses.setArrearId(arrears.getId());
                        arrearExpenses.setExpenseId(expenses.getId());
                        arrearExpenses.setSyncFlag(0);
                        arrearExpensesService.save(arrearExpenses);
                    }
                }
                //修改抄表记录的审核状态
                recordsService.update(new LambdaUpdateWrapper<MrRecords>()
                        .set(MrRecords::getAuditStatus,1)
                        .eq(MrRecords::getId,recordVo.getId()));
            }
            //审核记录
            MrAudits mrAudits = new MrAudits();
            mrAudits.setCustomerId(recordVo.getCustomerId());
            mrAudits.setCusName(recordVo.getCusName());
            mrAudits.setRecordId(recordVo.getId());
            mrAudits.setBeginScale(recordVo.getBeginScale());
            mrAudits.setEndScale(recordVo.getEndScale());
            mrAudits.setAmount(recordVo.getAmount());
            mrAudits.setIsPassed(isPass);
            mrAudits.setWaterUsedType(recordVo.getWaterUsedType());
            mrAudits.setAuditedAdvice(note);
            auditsService.save(mrAudits);

            cusIds.add(recordVo.getCustomerId());
            //if (isPass == 1) {
            //    String format = String.format("%s =  %s - %s", "unread_times", "unread_times", 1);
            //    customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
            //            .setSql(format).in(ArcCustomers::getId, cusIds)
            //            .gt(ArcCustomers::getUnreadTimes,-1));
            //}
        }

        if (isPass == 1 && null != readRecordVos && readRecordVos.size()>0) {
            /**首页数据动态更新*/
            /**设置首页数据动态更新-退费*/
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        chgFeesService.indexData(null,null);;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        log.warn("首页数据动态更新");
                    }
                }
            }).start();
        }
        return Result.OK("OK");
    }

    /**创建欠费记录及明细*/
    private ChgArrearsPage createArrears(Integer isPreinvoiced, MsMeasures measures
            ,BlExpenses expenses, List<BlSubExpenses> blSubExpensesList) {

        List<ChgSubArrear> subArrearsLs=new ArrayList<>();
        for (BlSubExpenses blSubExpenses : blSubExpensesList) {
            ChgSubArrear subArrears = new ChgSubArrear();
            subArrears.setSubExpenseId(blSubExpenses.getId());
            subArrears.setItemCode(blSubExpenses.getItemCode());
            subArrears.setPriceId(blSubExpenses.getPriceId());
            subArrears.setNatureId(blSubExpenses.getNatureId());
            subArrears.setTierNo(blSubExpenses.getTierNo());
            subArrears.setPrice(blSubExpenses.getPrice());
            subArrears.setAmount(blSubExpenses.getAmount());
            subArrears.setArrearAmount(subArrears.getAmount());
            subArrears.setTotalMoney(blSubExpenses.getTotalMoney());
            subArrears.setVatMoney(blSubExpenses.getVatMoney());
            subArrears.setDiscountMoney(blSubExpenses.getDiscountMoney());
            subArrears.setMoney(blSubExpenses.getMoney());
            subArrears.setArrearMoney(subArrears.getMoney());
            subArrears.setRecivedMoney(new BigDecimal(0.0));
            if(isPreinvoiced ==1){
                //是预开票
                subArrears.setIsLocked(1);
                subArrears.setLockedTypeId("1");
            }else{
                subArrears.setIsLocked(0);
            }
            subArrears.setSyncFlag(0);
            subArrearsLs.add(subArrears);
        }

        ChgArrearsPage arrears = new ChgArrearsPage();
        arrears.setCusId(expenses.getCustomerId());
        arrears.setCusName(expenses.getCusName());
        arrears.setNatureId(expenses.getNatureId());
        arrears.setReadMonth(expenses.getReadMonth());
        arrears.setBeginScale(measures.getBeginScale());
        arrears.setEndScale(measures.getEndScale());
        arrears.setReadAmount(measures.getReadAmount());
        arrears.setReplaceAmount(measures.getReplaceAmount());
        arrears.setReplaceMeterScale(measures.getReplaceMeterScale());
        arrears.setAjustedAmount(measures.getAjustedAmount());
        arrears.setMeasureAmount(measures.getMeasureAmount());
        arrears.setAmount(expenses.getAmount());
        arrears.setTotalMoney(expenses.getTotalMoney());
        arrears.setVatMoney(expenses.getVatMoney());
        arrears.setDiscountMoney(expenses.getDiscountMoney());
        arrears.setMoney(expenses.getMoney());
        arrears.setReaderId(expenses.getReaderId());
        arrears.setBookId(expenses.getBookId());
        arrears.setReadTime( null != measures.getReadTime() ? DateUtils.formatDate(measures.getReadTime()): null);
        arrears.setWaterUsedType(measures.getWaterUsedType());
        arrears.setRecivedAmount(new BigDecimal(0.0));
        arrears.setRecivedMoney(new BigDecimal(0.0));
        arrears.setArrearMoney(arrears.getMoney());
        arrears.setLockedAmount(new BigDecimal(0.0));
        arrears.setLockedMoney(new BigDecimal(0.0));
        arrears.setArrearAmount(arrears.getAmount());

        arrears.setChgSubArrearList(subArrearsLs);

        return arrears;

    }

    /**查询用户的换表记录 @return*/
    private JSONObject queryReplace(Integer isPass, String readMonth, String customerId) {
        JSONObject repObj=new JSONObject();
        BigDecimal replaceAmount=new BigDecimal(0.0);
        BigDecimal replaceScale=new BigDecimal(0.0);

        ////没有计算  的换表记录
        List<ArcMeterReplaces> replacesList = replacesService.list(
                new LambdaQueryWrapper<ArcMeterReplaces>()
                        .eq(ArcMeterReplaces::getCustomerId, customerId)
                        //  .likeLeft(ArcMeterReplaces::getReplacedTime,DateUtils.getDate("yyyy-MM"))//计算方式有下次情况
                        .eq(ArcMeterReplaces::getIsCalculated, 0));
        if(null != replacesList && replacesList.size()>0){
            ArcMeterReplaces meterReplaces = replacesList.get(0);
            if("1".equals(meterReplaces.getWaterComputeType())){
                //立即计算，下次计算，不计算
                replaceAmount=meterReplaces.getOldAmount();//换表水量
                replaceScale=meterReplaces.getOldEndScale();
                if(isPass==1) {
                    replacesService.update(new LambdaUpdateWrapper<ArcMeterReplaces>()
                            .eq(ArcMeterReplaces::getId,meterReplaces.getId())
                            .set(ArcMeterReplaces::getIsCalculated,1));
                }

            }else if("2".equals(meterReplaces.getWaterComputeType())){
                //校验是否同一月份
                String repDate = DateUtils.formatDate(meterReplaces.getReplacedTime(), "yyyy-MM");
                if(!readMonth.equals(repDate)){
                    replaceAmount=meterReplaces.getOldAmount();//换表水量
                    replaceScale=meterReplaces.getOldEndScale();
                    if(isPass==1) {
                        replacesService.update(new LambdaUpdateWrapper<ArcMeterReplaces>()
                                .eq(ArcMeterReplaces::getId,meterReplaces.getId())
                                .set(ArcMeterReplaces::getIsCalculated,1));
                    }
                }
            }
        }
        repObj.put("replaceAmount",replaceAmount);
        repObj.put("replaceScale",replaceScale);
        return repObj;
    }

    private BlExpensesPage createExpense(ReadRecordVo recordVo,MsMeasuresPage measurePage) {
        String customerId = measurePage.getCustomerId();
        //计费水量
        BigDecimal amount = measurePage.getAmount();
        List<BlSubExpenses>subExpLs=new ArrayList<>();

        SysVarModel varModel = baseAPI.querySysVar("vat_rate");
        if(null ==varModel){
            varModel= new SysVarModel();
            varModel.setValue("0.13");
        }

        //优惠收费项
        List<BlSubDiscounts> discountItemList = discountsService.queryDiscountItemByCusId(customerId);

        //用水性质对应用水价格
        List<BaseWaterPricesVo> pricesVos = waterPricesService.queryWaterPriceByNatureId(recordVo.getNatureId(),"0");

        /**
         * 01	水费
         * 02	违约金
         * 03	污水处理费
         * 04	杂项工程费
         * 05	二次加压费
         * 06	季节性加价
         * 07	代收垃圾费
         */
        //统计明细水费
        BigDecimal sfm=new BigDecimal(0.0);
        //统计明细污水费
        BigDecimal wum=new BigDecimal(0.0);
        //统计明细增值税
        BigDecimal vm=new BigDecimal(0.0);
        //统计明细垃圾费
        BigDecimal ljm=new BigDecimal(0.0);
        //统计明细杂项费
        BigDecimal zam=new BigDecimal(0.0);
        //统计明加压加费
        BigDecimal jym=new BigDecimal(0.0);
        //统计明细季加费
        BigDecimal jim=new BigDecimal(0.0);
        //统计明细折扣费
        BigDecimal dism=new BigDecimal(0.0);
        if(null != pricesVos && pricesVos.size()>0){

            JSONObject priceObj=new JSONObject();
            Set<String> tirPriceSet= new HashSet<String>();

            //按阶梯分组
            for (BaseWaterPricesVo pricesVo : pricesVos) {
                String key=pricesVo.getTierNo()+"";
                JSONArray itemArr=new JSONArray();
                if(!tirPriceSet.contains(key)){
                    tirPriceSet.add(key);
                    for (BaseWaterPricesVo priVo : pricesVos) {
                        String pkey=priVo.getTierNo()+"";
                        if(key.equals(pkey)){
                            itemArr.add(priVo);
                        }
                    }
                    priceObj.put(key,itemArr);
                }
            }

            //固定的只收一次
            int fixIndex=0;
            for(int i=0;i<priceObj.keySet().size();i++){
                String key=i+"";
                if(null != priceObj.get(key)){
                    //同一阶梯值
                    BigDecimal tempAmount=new BigDecimal(0.0);
                    int index=0;

                    for (Object itemo : priceObj.getJSONArray(key)) {
                        BaseWaterPricesVo pricesVo= (BaseWaterPricesVo) itemo;
                        if(pricesVo.getTierTypeId()==1) {//每月阶梯
                            BlSubExpenses subExpenses = new BlSubExpenses();
                            if(index==0){
                                if (amount.subtract(pricesVo.getTierAmount()).doubleValue() > 0) {
                                    subExpenses.setAmount(pricesVo.getTierAmount());
                                } else {
                                    subExpenses.setAmount(amount);
                                }
                                tempAmount=subExpenses.getAmount();
                            }else{
                                subExpenses.setAmount(tempAmount);
                            }
                            subExpenses.setNatureId(recordVo.getNatureId());
                            subExpenses.setItemCode(pricesVo.getCode());
                            subExpenses.setPriceId(pricesVo.getPriceId());
                            subExpenses.setPrice(pricesVo.getPrice());
                            subExpenses.setTierNo(pricesVo.getTierNo());

                            if( null != pricesVo.getIsFix() && 1 == pricesVo.getIsFix()){
                                if(fixIndex==0){
                                    subExpenses.setTotalMoney(pricesVo.getPrice());
                                }else{
                                    subExpenses.setTotalMoney(new BigDecimal(0.0).setScale(2));
                                }
                                subExpenses.setDiscountMoney(new BigDecimal(0.0));
                                subExpenses.setVatMoney(new BigDecimal(0.0));
                                subExpenses.setAmount(new BigDecimal(0.0));
                                fixIndex++;
                            }else{
                                subExpenses.setTotalMoney(subExpenses.getPrice().multiply(subExpenses.getAmount())
                                        .setScale(2, BigDecimal.ROUND_HALF_UP));

                                //优惠方案折扣情况
                                if(null != discountItemList && discountItemList.size()>0){
                                    for (BlSubDiscounts blSubDiscounts : discountItemList) {
                                        if(pricesVo.getCode().equals(blSubDiscounts.getCode())
                                                && blSubDiscounts.getIsReduced() ==1){
                                            //同一收费项目，并且允许减免的，
                                            if("1".equals(blSubDiscounts.getWaterConfigsType())){
                                                //固定值
                                                BigDecimal subtract = subExpenses.getTotalMoney().subtract(blSubDiscounts.getValue());
                                                if(subtract.doubleValue()>=0){
                                                    subExpenses.setDiscountMoney(blSubDiscounts.getValue());
                                                }else{
                                                    subExpenses.setDiscountMoney(subExpenses.getTotalMoney());
                                                }
                                            }else if("2".equals(blSubDiscounts.getWaterConfigsType())){
                                                //比例
                                                BigDecimal multiplyVal = subExpenses.getTotalMoney()
                                                        .multiply(blSubDiscounts.getValue())
                                                        .setScale(2, BigDecimal.ROUND_HALF_UP);
                                                BigDecimal subtract = subExpenses.getTotalMoney().subtract(multiplyVal);
                                                if(subtract.doubleValue()>=0){
                                                    subExpenses.setDiscountMoney(multiplyVal);
                                                }else{
                                                    subExpenses.setDiscountMoney(subExpenses.getTotalMoney());
                                                }
                                            }
                                            subExpenses.setDiscountId(blSubDiscounts.getDiscountId());
                                        }
                                    }
                                }
                            }
                            if( null == subExpenses.getDiscountMoney()){
                                subExpenses.setDiscountMoney(new BigDecimal(0.0));
                            }
                            //收费项目是要计算增值税的，计算到明细，
                            if(pricesVo.getIsVat()==1){
                                BigDecimal subtract = subExpenses.getTotalMoney().subtract(subExpenses.getDiscountMoney());
                                subExpenses.setVatMoney(subtract.multiply(new BigDecimal(varModel.getValue()))
                                        .setScale(2, BigDecimal.ROUND_HALF_UP));
                            }else {
                                subExpenses.setVatMoney(new BigDecimal(0.0));
                            }
                            if("01".equals(subExpenses.getItemCode())){
                                //水费
                                sfm=sfm.add(subExpenses.getTotalMoney());
                            }else if("03".equals(subExpenses.getItemCode())){
                                //污水
                                wum=wum.add(subExpenses.getTotalMoney());
                            }else if("04".equals(subExpenses.getItemCode())){
                                //杂项工程费
                                zam=zam.add(subExpenses.getTotalMoney());
                            }else if("05".equals(subExpenses.getItemCode())){
                                //二次加压费
                                jym=jym.add(subExpenses.getTotalMoney());
                            }else if("06".equals(subExpenses.getItemCode())){
                                //季节性加价
                                jim=jim.add(subExpenses.getTotalMoney());
                            }else if("07".equals(subExpenses.getItemCode())){
                                //代收垃圾费
                                ljm=ljm.add(subExpenses.getTotalMoney());
                            }
                            //增值税
                            vm=vm.add(subExpenses.getVatMoney());
                            //折扣
                            dism=dism.add(subExpenses.getDiscountMoney());

                            subExpenses.setMoney(subExpenses.getTotalMoney()
                                    .subtract(subExpenses.getDiscountMoney())
                                    .add(subExpenses.getVatMoney()));
                            subExpenses.setTierNo(pricesVo.getTierNo());
                            subExpLs.add(subExpenses);
                            index++;
                        }
                    }
                    amount=amount.subtract(tempAmount);
                }
            }
        }

        BlExpensesPage expensesPage = new BlExpensesPage();
        expensesPage.setBookId(measurePage.getBookId());
        expensesPage.setCusName(measurePage.getCusName());
        expensesPage.setCustomerId(measurePage.getCustomerId());
        expensesPage.setReadMonth(measurePage.getReadMonth());
        expensesPage.setFinancialMonth(measurePage.getFinancialMonth());
        expensesPage.setFinancialDate(measurePage.getFinancialDate());
        expensesPage.setNatureId(recordVo.getNatureId());
        //expensesPage.setPriceId();
        //expensesPage.setIsStruck();
        expensesPage.setReaderId(measurePage.getReaderId());
        expensesPage.setTotalMoney(sfm);
        expensesPage.setWuMoney(wum);
        expensesPage.setAlienMoney(zam);
        expensesPage.setJyMoney(jym);
        expensesPage.setJiMoney(jim);
        expensesPage.setLjMoney(ljm);
        expensesPage.setDiscountMoney(dism);
        expensesPage.setVatMoney(vm);

        //折后合计
        BigDecimal money = expensesPage.getTotalMoney().add(expensesPage.getWuMoney()).add(expensesPage.getAlienMoney())
                .add(expensesPage.getJyMoney()) .add(expensesPage.getJiMoney()) .add(expensesPage.getLjMoney())
                .add(expensesPage.getVatMoney()).subtract(expensesPage.getDiscountMoney())
                .setScale(2,BigDecimal.ROUND_HALF_UP);

        expensesPage.setMoney(money);
        expensesPage.setAmount(measurePage.getAmount());
        expensesPage.setBlSubExpensesList(subExpLs);
        return expensesPage;
    }


    /**
     * 创建Online 记录
     * @param code
     * @param jsonObject
     */
    @Override
   public void createOnlineData(String code, JSONObject jsonObject){
       //水量优惠记录
       OnlCgformHead head = (OnlCgformHead) cgformHeadService.getById(code);
       String tableName = head.getTableName();
       LambdaQueryWrapper<OnlCgformField> formFieldWrapper = new LambdaQueryWrapper();
       formFieldWrapper.eq(OnlCgformField::getCgformHeadId, code);
       formFieldWrapper.eq(OnlCgformField::getIsShowForm, 1);
       List<OnlCgformField> formFieldLs = cgformFieldService.list(formFieldWrapper);
       cgformFieldService.saveFormData(formFieldLs,tableName,jsonObject);
    }

    /**
     *  水量修改-对已审核（已计量计费已欠费记录）的进行回头修改，没有审核的则可以直接在抄表录入直接修改，已收费的则不出现
     *
     * 水量修改分成三种情况，已抄未审，本月已审，往月水量。
     * 对于已抄未审，直接修改原记录，
     * 本月已审和往月水量修改均新生成抄表记录，然后根据参数调用是否自动审核。修改水量后，需要重新审核通过计费或复审（复审后再重新审核计费），
     * 本月已审修改水量，原来抄表记录作为无效，新增一条抄表记录，抄表审核需要重新审核计费
     * @param changesRecordVo
     */
    @Override
    @Transactional
    public Result<?> changesAmount(ChangesRecordVo changesRecordVo) {

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        /***
         * 1   是否有审核计量计费记录
         * 2   是否是最新月份月份抄表修改，是需要修改用户最后抄表读数
         * 3   是否存在下月份的抄表记录，修改修改起度
         *
         */

        MrRecords mrRecords = recordsMapper.selectById(changesRecordVo.getRecordId());
        if(null != mrRecords){

            Integer auditInt = exitsChangeAudits(mrRecords.getId());
            if(auditInt == - 1){
                new JeecgBootException("已收费修改");
            }else if(auditInt == 1){
                //原抄表记录作为无效，再新增一条
                recordsMapper.update(mrRecords,new LambdaUpdateWrapper<MrRecords>()
                        .set(MrRecords::getIsVaild,0)
                        .set(MrRecords::getAuditStatus,0)
                        .eq(MrRecords::getId,mrRecords.getId())
                );

                MrRecords records = new MrRecords();
                BeanUtils.copyProperties(mrRecords, records);
                records.setIsVaild(1);
                records.setAuditStatus(0);
                records.setId(null);
                //当前条不用考虑状态
                records.setEndScale(changesRecordVo.getNewEndScale());
                records.setAmount(changesRecordVo.getNewAmount());
                recordsMapper.insert(records);

                //创建水量修改记录
                createMrChanges(mrRecords,changesRecordVo,sysUser);

                customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                        .set(ArcCustomers::getLastReadScale,records.getEndScale())//最后抄表止度
                        .eq(ArcCustomers::getCode, records.getCustomerId())//用户编号
                       );
            }else {
                //没有审核-直接修改原来记录-也不会进来，没有审核则直接抄表录入直接修改
                //mrRecords.setEndScale(changesRecordVo.getNewEndScale());
                //mrRecords.setAmount(changesRecordVo.getNewAmount());
                //recordsMapper.updateById(mrRecords);

                //创建水量修改记录
                createMrChanges(mrRecords,changesRecordVo,sysUser);

                recordsMapper.update(mrRecords,new LambdaUpdateWrapper<MrRecords>()
                        .eq(MrRecords::getId,mrRecords.getId())
                        .set(MrRecords::getEndScale,changesRecordVo.getNewEndScale())
                        .set(MrRecords::getAmount,changesRecordVo.getNewAmount()));

                customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                        .set(ArcCustomers::getLastReadScale,mrRecords.getEndScale())//最后抄表止度
                        .eq(ArcCustomers::getCode, mrRecords.getCustomerId())//用户编号
                );
            }
            //是否存在下月份的抄表记录-存在则修改第一条起度
            String readMonth = mrRecords.getReadMonth();
            List<MrRecords> recordsList = recordsMapper.selectList(new LambdaQueryWrapper<MrRecords>()
                    .eq(MrRecords::getCustomerId, mrRecords.getCustomerId())
                    .eq(MrRecords::getIsVaild, 1)
                    .eq(MrRecords::getDelFlag, 0)
                    .gt(MrRecords::getReadMonth, readMonth)//大于当前抄表月份
                    .orderByAsc(MrRecords::getReadMonth));
            if(null != recordsList && recordsList.size()>0){
                MrRecords records = recordsList.get(0);
                //处理已计量已计费已欠费记录
                auditInt = exitsChangeAudits(records.getId());
                if(auditInt == - 1){
                    new JeecgBootException("已收费修改");
                }else if(auditInt==1){
                    //原抄表记录作为无效，再新增一条
                    //records.setIsVaild(0);
                    //recordsMapper.updateById(records);
                    recordsMapper.update(records,new LambdaUpdateWrapper<MrRecords>()
                            .set(MrRecords::getIsVaild,0)
                            .set(MrRecords::getAuditStatus,0)
                            .eq(MrRecords::getId,records.getId())
                    );

                    MrRecords newRecords = new MrRecords();
                    BeanUtils.copyProperties(records, newRecords);
                    newRecords.setIsVaild(1);
                    newRecords.setId(null);

                    //下一条的需要考虑状态
                    if("1".equals(newRecords.getWaterUsedType())){
                        newRecords.setBeginScale(changesRecordVo.getNewEndScale());
                        newRecords.setAmount( newRecords.getEndScale().subtract(newRecords.getBeginScale()));
                    }else {
                        newRecords.setBeginScale(changesRecordVo.getNewEndScale());
                        //非正常状态-水量就是原本的手写水量-不变
                    }
                    recordsMapper.insert(newRecords);
                }else {
                    //没有审核-直接修改下个月份的原记录
                    if("1".equals(records.getWaterUsedType())){
                        records.setBeginScale(changesRecordVo.getNewEndScale());
                        recordsMapper.update(records,new LambdaUpdateWrapper<MrRecords>()
                                .set(MrRecords::getBeginScale,changesRecordVo.getNewEndScale())
                                .set(MrRecords::getAmount,records.getEndScale().subtract(records.getBeginScale()))
                                .eq(MrRecords::getId,records.getId()));
                    }else{
                        recordsMapper.update(records,new LambdaUpdateWrapper<MrRecords>()
                                .eq(MrRecords::getId,records.getId())
                                .set(MrRecords::getBeginScale,changesRecordVo.getNewEndScale()));
                    }
                }
            }else{
                //没有下个月份的，则是最新的，则 需要修改用户最后抄表读数
               customersService.update(new LambdaUpdateWrapper<ArcCustomers>()
                       .eq(ArcCustomers::getId,mrRecords.getCustomerId())
                       .set(ArcCustomers::getLastReadScale, changesRecordVo.getNewEndScale()));

            }
        }
        return Result.OK("修改成功");
    }

    //创建水量修改记录
    void createMrChanges(MrRecords mrRecords,ChangesRecordVo changesRecordVo, LoginUser sysUser ){
        MrChanges mrChanges = new MrChanges();
        mrChanges.setCusName(mrRecords.getCusName());
        mrChanges.setCustomerId(mrRecords.getCustomerId());
        mrChanges.setOldEndScale(mrRecords.getEndScale());
        mrChanges.setOldAmount(mrRecords.getAmount());
        mrChanges.setNewEndScale(changesRecordVo.getNewEndScale());
        mrChanges.setNewAmount(changesRecordVo.getNewAmount());
        mrChanges.setOperatorId(sysUser.getUsername());
        mrChanges.setOperatedTime(new Date());
        mrChanges.setReadMonth(mrRecords.getReadMonth());
        changesService.save(mrChanges);
    }

    //水量修改-存在计量计费审核记录作为无效
    public Integer exitsChangeAudits(String recordId){
        int rs=0;
        BigDecimal zero = new BigDecimal(0.0);
        List<MrAudits> auditsList = auditsService.list(new LambdaQueryWrapper<MrAudits>()
                .eq(MrAudits::getRecordId, recordId)
                .eq(MrAudits::getIsVaild, 1)
                .eq(MrAudits::getDelFlag, 0)
                .eq(MrAudits::getIsPassed,1));

        if(null != auditsList &&auditsList.size()>0) {

            //已存在有效通过的审核记录--水量修改 要修改为无效
            MrAudits audits = auditsList.get(0);

            //校验是否已收费了（欠费记录不存在表示收费了）
            List<RecordMEArrearVo> arrearVoList = expensesService.queryRecordMEArrear(recordId);
            if(null != arrearVoList && arrearVoList.size()>0){
                RecordMEArrearVo recordMEArrearVo = arrearVoList.get(0);
                if(oConvertUtils.isEmpty(recordMEArrearVo.getArrearId())){
                    //欠费ID 为空 则已收费了
                    return -1;
                }

                //欠费还存在，没有收费

                //计量的-作废
                MsMeasures measures = measuresService.getById(recordMEArrearVo.getMeasureId());
                measuresService.update(new LambdaUpdateWrapper<MsMeasures>()
                        .set(MsMeasures::getIsVaild,0)
                        .eq(MsMeasures::getId,measures.getId())
                        .eq(MsMeasures::getDelFlag,0)
                        .eq(MsMeasures::getIsVaild,1));
                //存在用水优惠记录-删除
                if(measures.getAjustedAmount().doubleValue()>0){
                    OnlCgformHead head = (OnlCgformHead) cgformHeadService.getById("402881a57ee161d4017ee1621ee70001");
                    String tableName = head.getTableName();
                    cgformFieldService.deleteAutoList(tableName,"record_id",recordId);
                }
                //删除计量明细
                measuresService.delSubByMainId(measures.getId());

                //计费记录-作废--存在杂项合并
                BlExpenses expenses = expensesService.getById(recordMEArrearVo.getExpenseId());
                if(expenses.getAlienMoney().doubleValue()>0){
                    //存在杂项费- 水费、增值税、折扣费都置0，折后金额直接等于杂项费
                    expensesService.update(new LambdaUpdateWrapper<BlExpenses>()
                            .set(BlExpenses::getAmount,zero)
                            .set(BlExpenses::getTotalMoney,zero)
                            .set(BlExpenses::getVatMoney,zero)
                            .set(BlExpenses::getDiscountMoney,zero)
                            .set(BlExpenses::getMoney,expenses.getAlienMoney())
                            .eq(BlExpenses::getId,recordMEArrearVo.getExpenseId())
                            .eq(BlExpenses::getDelFlag,0)
                            .eq(BlExpenses::getIsValid,1));
                    //删除计费明细
                    expensesService.delSubByMainId(recordMEArrearVo.getExpenseId());

                }else{
                    expensesService.update(new LambdaUpdateWrapper<BlExpenses>()
                            .set(BlExpenses::getIsValid,0)
                            .set(BlExpenses::getDelFlag,1)
                            .eq(BlExpenses::getId,recordMEArrearVo.getExpenseId())
                            .eq(BlExpenses::getDelFlag,0)
                            .eq(BlExpenses::getIsValid,1));
                    //删除计费明细
                    expensesService.delSubByMainId(recordMEArrearVo.getExpenseId());

                }

                //存在优惠计费记录的，删除
                discountFeesService.update(new LambdaUpdateWrapper<BlDiscountFees>()
                        .set(BlDiscountFees::getDelFlag, 1)
                        .eq(BlDiscountFees::getExpenseId, recordMEArrearVo.getExpenseId())
                        .eq(BlDiscountFees::getDelFlag, 0));

                //欠费记录-作废
                ChgArrears arrears = arrearsService.getById(recordMEArrearVo.getArrearId());
                if(arrears.getAlienMoney().doubleValue()>0){
                    //存在杂项- 水费、增值税、折扣费都置0，折后金额直接等于杂项费
                    arrearsService.update(new LambdaUpdateWrapper<ChgArrears>()
                            .set(ChgArrears::getTotalMoney,zero)
                            .set(ChgArrears::getVatMoney,zero)
                            .set(ChgArrears::getBeginScale,zero)
                            .set(ChgArrears::getEndScale,zero)
                            .set(ChgArrears::getReadAmount,zero)
                            .set(ChgArrears::getAmount,zero)
                            .set(ChgArrears::getAjustedAmount,zero)
                            .set(ChgArrears::getMeasureAmount,zero)
                            .set(ChgArrears::getArrearAmount,zero)
                            .set(ChgArrears::getDiscountMoney,zero)
                            .set(ChgArrears::getMoney,expenses.getAlienMoney())
                            .set(ChgArrears::getArrearMoney,expenses.getAlienMoney())
                            .eq(ChgArrears::getId,recordMEArrearVo.getArrearId())
                            .eq(ChgArrears::getDelFlag,0));
                    //删除水费欠费明细
                    arrearsService.delSubByMainId(recordMEArrearVo.getArrearId());
                }else{
                    arrearsService.update(new LambdaUpdateWrapper<ChgArrears>()
                            .set(ChgArrears::getDelFlag,1)
                            .eq(ChgArrears::getId,recordMEArrearVo.getArrearId())
                            .eq(ChgArrears::getDelFlag,0));
                    //删除水费欠费明细
                    arrearsService.delSubByMainId(recordMEArrearVo.getArrearId());
                }

                //欠费与计费关联
                arrearExpensesService.update(new LambdaUpdateWrapper<ChgArrearExpenses>()
                        .set(ChgArrearExpenses::getDelFlag,1)
                        .eq(ChgArrearExpenses::getId,recordMEArrearVo.getExpenseArrearId())
                        .eq(ChgArrearExpenses::getDelFlag,0));
            }

            //audits.setIsVaild(0);
            //auditsService.updateById(audits);
            auditsService.update(new LambdaUpdateWrapper<MrAudits>()
                    .eq(MrAudits::getId,audits.getId())
                    .set(MrAudits::getIsVaild,0));

            rs=1;
        }
        return rs;
    }

    /**
     *   创建计量
     * 抄见水量=水表止度-起度+手工增减修正(估抄修正).
     * 实用水量=抄见量+总分表分配水量(分摊水量)+换表水量
     * 计量水量=实用水量+水表计量增减(考核表不计量)
     * 计费水量=计量水量+计费增减水量(优惠、折扣、不计费)
     *
     * @param recordVo
     * @param finMonth
     * @param replaceScale
     * @param replaceAmount
     * @return
     * @throws ParseException
     */
    private MsMeasuresPage createMeasurePage(ReadRecordVo recordVo,String readMonth,String finMonth
            ,BigDecimal replaceScale,BigDecimal replaceAmount) throws ParseException {
        MsMeasuresPage msMeasures = new MsMeasuresPage();

        msMeasures.setCustomerId(recordVo.getCustomerId());
        msMeasures.setCusName(recordVo.getCusName());
        msMeasures.setBookId(recordVo.getBookId());
        msMeasures.setReaderId(recordVo.getReaderId());
        msMeasures.setRecordId(recordVo.getId());
        msMeasures.setReadMonth(readMonth);

        msMeasures.setReadTime(DateUtils.parseDate(recordVo.getReadTime(),"yyyy-MM-dd hh:mm:ss") );
        msMeasures.setIsTemp(0);
        msMeasures.setFinancialMonth(finMonth);
        msMeasures.setFinancialDate(new Date());
        msMeasures.setWaterUsedType(recordVo.getWaterUsedType());

        msMeasures.setBeginScale(recordVo.getBeginScale());
        msMeasures.setEndScale(recordVo.getEndScale());
        //水表抄见水量
        BigDecimal readScale = recordVo.getEndScale().subtract(recordVo.getBeginScale());
        //手工增减修正(估抄修正) = 水量数-抄见水量 不等就是调整的
        msMeasures.setReadAjustedAmount(recordVo.getAmount().subtract(readScale));
        msMeasures.setReadAmount(recordVo.getAmount());
        //shareAmount 总分表分摊水量
        msMeasures.setShareAmount(new BigDecimal(0.0));
        msMeasures.setReplaceMeterScale(replaceScale);//换表
        msMeasures.setReplaceAmount(replaceAmount);//换表

        //实用水量 usedAmount =抄见量+总分表分配水量(分摊水量)+换表水量
        msMeasures.setUsedAmount(msMeasures.getReadAmount()
                .add(msMeasures.getShareAmount()
                        .add(msMeasures.getReplaceAmount())));
        //measureAjustedAmount 计量增减水量 (考核表不计量) -这里是指 增减水量有减考核表，
        msMeasures.setMeasureAjustedAmount(new BigDecimal(0.0));
        //measureAmount 计量水量=使用水量+水表计量增减(考核表不计量)
        msMeasures.setMeasureAmount(msMeasures.getUsedAmount().add(msMeasures.getMeasureAjustedAmount()));

        //ajustedAmount 计费增减水量(优惠、折扣、不计费)
        msMeasures.setAjustedAmount(
                adjustedConfigsService.measureAdjustAmount(
                        recordVo.getCustomerId(),msMeasures.getUsedAmount()));
        //计费水量=计量水量-计费增减水量(优惠、折扣、不计费)
        msMeasures.setAmount(msMeasures.getMeasureAmount().subtract(msMeasures.getAjustedAmount()));

        msMeasures.setMsSubMeasuresList(createTier(recordVo,msMeasures.getAmount()));
        return msMeasures;
    }


    //创建阶梯-计量明细
    private List<MsSubMeasures> createTier(ReadRecordVo recordVo, BigDecimal amount) {
        BigDecimal total_decimal = amount;
        List<MsSubMeasures> subMeasuresLs=new ArrayList<>();

        if(recordVo.getIsTieredPrice() ==1){
            if(total_decimal.doubleValue()>0){
                MsSubMeasures subMeasures = new MsSubMeasures();
                subMeasures.setTierNo(0);
                if(total_decimal.subtract(recordVo.getTier0()).doubleValue()>0){
                    subMeasures.setExpenseAmount(recordVo.getTier0());
                    total_decimal= total_decimal.subtract(recordVo.getTier0());
                }else{
                    subMeasures.setExpenseAmount(total_decimal);
                    total_decimal= total_decimal.subtract(total_decimal);
                }
                subMeasures.setNatureId(recordVo.getNatureId());
                subMeasuresLs.add(subMeasures);
            }

            if(total_decimal.doubleValue()>0){
                MsSubMeasures subMeasures1 = new MsSubMeasures();
                subMeasures1.setTierNo(1);
                if(total_decimal.subtract(recordVo.getTier1()).doubleValue()>0){
                    subMeasures1.setExpenseAmount(recordVo.getTier1());
                    total_decimal= total_decimal.subtract(recordVo.getTier1());
                }else{
                    subMeasures1.setExpenseAmount(total_decimal);
                    total_decimal= total_decimal.subtract(total_decimal);
                }
                subMeasures1.setNatureId(recordVo.getNatureId());
                subMeasuresLs.add(subMeasures1);
            }

            if(total_decimal.doubleValue()>0){
                MsSubMeasures subMeasures2 = new MsSubMeasures();
                subMeasures2.setTierNo(2);
                if(total_decimal.subtract(recordVo.getTier2()).doubleValue()>0){
                    subMeasures2.setExpenseAmount(recordVo.getTier2());
                    total_decimal= total_decimal.subtract(recordVo.getTier2());
                }else{
                    subMeasures2.setExpenseAmount(total_decimal);
                    total_decimal= total_decimal.subtract(total_decimal);
                }
                subMeasures2.setNatureId(recordVo.getNatureId());
                subMeasuresLs.add(subMeasures2);
            }
        }else{
            if(total_decimal.doubleValue()>0){
                MsSubMeasures subMeasures = new MsSubMeasures();
                subMeasures.setTierNo(0);
                if(total_decimal.subtract(recordVo.getTier0()).doubleValue()>0){
                    subMeasures.setExpenseAmount(recordVo.getTier0());
                    total_decimal= total_decimal.subtract(recordVo.getTier0());
                }else{
                    subMeasures.setExpenseAmount(total_decimal);
                    total_decimal= total_decimal.subtract(total_decimal);
                }
                subMeasures.setNatureId(recordVo.getNatureId());
                subMeasuresLs.add(subMeasures);
            }
        }
        return  subMeasuresLs;
    }

    @Override
    public List<ReadRecordVo> queryReadMeasureRecord(List<String> rdIds) {
        return recordsMapper.queryReadMeasureRecord(rdIds);
    }

    @Override
    public List<MrRecords> queryPendingRecords(MrRecords query) {
        return recordsMapper.queryPendingRecords(query);
    }

    @Override
    public List<MrRecords> queryChangeRecords(MrRecords query) {
        return recordsMapper.queryChangeRecords(query);
    }

    @Override
    public List<MrIndexDataVO> queryMrIndexDataAccount() {
        return recordsMapper.queryMrIndexDataAccount();
    }

    @Override
    public List<MrIndexDataVO> queryMrIndexDataAudit() {
        return recordsMapper.queryMrIndexDataAudit();
    }

    @Override
    public List<MrBookReadsVO> queryBookReadCount(MrRecords query) {
        return recordsMapper.queryBookReadCount(query);
    }

    @Override
    @Transactional
    public Result<?> readRemoteManual(ReadRecordVo recordVo) {

        String[] cusIds = recordVo.getCustomerId().split(",");
        for (String cusId : cusIds) {
            if(StringUtils.isEmpty(cusId)){
                continue;
            }
            /**1. 获取水表序列号 */
            ArcCustomers customers = customersService.getById(cusId);
            if(null == customers ){
                //水表户不存在
                return Result.error("水表户不存在");
            }
            if( customers.getIsRead() != 1){
                //本月不需要抄表
                return Result.error("本月不需要抄表");
            }
            if( "8".equals(customers.getWaterReadCycle())){
                //一月多抄

            }

            String manholeId = customers.getManholeId();//远程表序列号
            if(StringUtils.isEmpty(manholeId) || customers.getIsRemote() == 0){
                return Result.error("水表户不是远传表或水表序列号不存在");
            }

            /**2. 获取水表远程最新读数 */
            List<Map<String, Object>> readData = this.readRemote(manholeId);
            if(null == readData || readData.size() == 0){
                return Result.error("当前无远程最新读数");
            }

            /**3. 提交抄表记录 */

            /**
             * customerId
             * cusCode
             * cusName
             * address
             * mobile
             * beginScale
             * endScale
             * amount
             * readTime(抄表日期)
             * waterUsedType(水表状态)
             *
             */

            Object driveReadData = readData.get(0).get("driveReadData");
            if(null != driveReadData){
                recordVo.setEndScale(new BigDecimal(driveReadData.toString()).setScale(0,BigDecimal.ROUND_DOWN));
            }

            recordVo.setCustomerId(customers.getId());
            recordVo.setCusCode(customers.getCode());
            recordVo.setCusName(customers.getCusName());
            recordVo.setAddress(customers.getAddress());
            recordVo.setBeginScale(customers.getLastReadScale());
            recordVo.setReadTime(DateUtils.getDate("yyyy-MM-dd"));
            recordVo.setWaterUsedType("1");// 正常
            recordVo.setWaterReadInput("2");// 远传抄表
            recordVo.setBookId(customers.getBookId());

            BigDecimal scale = recordVo.getEndScale().subtract(recordVo.getBeginScale()).setScale(0, BigDecimal.ROUND_HALF_DOWN);
            if(scale.intValue()>0){
                recordVo.setAmount(scale);
            }else{
                recordVo.setAmount(BigDecimal.ZERO);
                recordVo.setRemark("止度小於起度，讀數計為0");
            }
            Result<?> result = this.readManual(recordVo);
            if(!result.isSuccess()){
                throw new JeecgBootException(result.getMessage());
            }
        }
        return Result.OK();
    }
}
